#include <iostream>
#include <string>
#include <queue>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include "Task.hpp"
#include "LockGuard.hpp"
#include "BlockQueue.hpp"

#define CONSUMERSIZE 5
#define PRODUCERSSIZE 5

#define CAPACITY 5
// Consumers, producers 消费者，生产者

template <class T>
struct ThreadData
{
    ThreadData(const std::string name, BlockQueue<T> *bq)
        : _bq(bq), _name(name)
    {
    }
    BlockQueue<T> *_bq;
    std::string _name;
};

void *consumers(void *args)
{

    // BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    ThreadData<Task> *td = static_cast<ThreadData<Task> *>(args);

    while (true)
    {
        // sleep(1);
        // 1.获取数据
        // int data;
        Task t;
        td->_bq->Pop(&t);
        t();
        std::cout << td->_name <<" , consumers data : " << t.PrintResult() << std::endl;
        // 2.消费
        // std::cout << "consumers data : " << data << "size : " << bq->Size() << std::endl;
    }
}

void *producers(void *args)
{
    // BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    // BlockQueue<int> *bq = static_cast<BlockQueue<int> *>(args);
    ThreadData<Task> *td = static_cast<ThreadData<Task> *>(args);
    while (true)
    {
        sleep(1);
        // 1.有数据、
        int x = rand() % 10 + 1; // [0,10]
        usleep(rand() % 123);
        int y = rand() % 10 + 1; // [0,10]
        usleep(rand() % 123);
        int op = rand() % opres.size();
        // 2.生产数据
        Task data(x, y, opres[op]);
        td->_bq->Push(data);

        std::cout << td->_name <<" , producers Task : " << data.PrintTask() << std::endl;
        // std::cout << "producers data : " << data << "size : " << bq->Size() << std::endl;
        // sleep(1);
    }
}

int main()
{

    // 单单
    //  srand((int16_t)time(nullptr) ^ getpid() ^ pthread_self()); // 生成的随机数更加随机
    //  // BlockQueue<int> *bq = new BlockQueue<int>(CAPACITY);
    //  BlockQueue<Task> *bq = new BlockQueue<Task>(CAPACITY);
    //  pthread_t c, p;

    // pthread_create(&c, nullptr, consumers, (void *)bq);
    // pthread_create(&p, nullptr, producers, (void *)bq);

    // pthread_join(c, nullptr);
    // pthread_join(p, nullptr);

    // 多多，可以直接改成多线程，加上name
    srand((int16_t)time(nullptr) ^ getpid() ^ pthread_self()); // 生成的随机数更加随机
    // BlockQueue<int> *bq = new BlockQueue<int>(CAPACITY);
    BlockQueue<Task> *bq = new BlockQueue<Task>(CAPACITY);
    pthread_t c[CONSUMERSIZE], p[PRODUCERSSIZE];

    for (int i = 0; i < CONSUMERSIZE; i++)
    {
        std::string name  = "consumer-";
        name += std::to_string(i);
        ThreadData<Task> *td = new ThreadData<Task>(name,bq);
        pthread_create(&c[i], nullptr, consumers, (void *)td);
    }

    for (int i = 0; i < PRODUCERSSIZE; i++)
    {
        std::string name  = "producers-";
        name += std::to_string(i);
        ThreadData<Task> *td = new ThreadData<Task>(name,bq);
        pthread_create(&p[i], nullptr, producers, (void *)td);
    }

    for (int i = 0; i < CONSUMERSIZE; i++)
    {
        pthread_join(c[i], nullptr);
    }

    for (int i = 0; i < PRODUCERSSIZE; i++)
    {
        pthread_join(p[i], nullptr);
    }

    return 0;
}